package sparql;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;

public class SparqlManager {
	private SparqlClient sparqlClient;
	private static String endpointUri = "localhost:3030/space";
	
    public SparqlManager() {
        sparqlClient = new SparqlClient(endpointUri);
    }
    
    public HashMap<String,Float> getInstance(String word){ // The query that retrieves the instance of a class
    	HashMap<String,Float> instances = new HashMap<String,Float>();
        String query = "PREFIX : <http://ontologies.alwaysdata.net/space#>\n"+
        		"PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"+
        		"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"+
        		"PREFIX owl:  <http://www.w3.org/2002/07/owl#>\n"+
        		"PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>\n"+
        		"SELECT ?label ?instance WHERE {\n"+
        		 	 "?class rdfs:label \""+word+"\"@fr.\n "+
        		     "?instance a ?class.\n"+
        		     "?instance rdfs:label ?label."+
        		"}\n";
        		 
            Iterable<Map<String, String>> results = this.sparqlClient.select(query);
            int nbResult = 0;
            for (Map<String, String> result : results) {
                nbResult++; // we count the results (not needed anymore, was used to ponderate weights
            }
            
            for (Map<String, String> result : results) {
            	ArrayList<String> arr = tokenizeResult(result.get("label"));
            	for (String s : arr){// each word is lemmatized before insertion
            		instances.put(xml.WordLemmatiser.lemmatize(s),0.5f); // we add a weight of 0.5
            	}
            }
        return instances;
    }
    
    public HashMap<String,Float> getRelatedTerms(String word){ // same as previous method but with sub classes
    	HashMap<String,Float> terms = new HashMap<String,Float>();
    	String query = "PREFIX : <http://ontologies.alwaysdata.net/space#>\n"+
        		"PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"+
        		"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"+
        		"PREFIX owl:  <http://www.w3.org/2002/07/owl#>\n"+
        		"PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>\n"+
        		"SELECT ?term WHERE {\n"+
        		 	 "?class rdfs:label \""+word+"\"@fr.\n "+
        		 	 "?subClass rdfs:subClassOf ?class.\n"+
        		     "?subClass rdfs:label ?term.\n"+
        		"}\n";
    	
    	Iterable<Map<String, String>> results = this.sparqlClient.select(query);
        int nbResult = 0;
        for (Map<String, String> result : results) {
            nbResult++;
        }
        
        for (Map<String, String> result : results) {
        	ArrayList<String> arr = tokenizeResult(result.get("term"));
        	for (String s : arr){
        		terms.put(xml.WordLemmatiser.lemmatize(s),0.5f);// we add a weightof 0.5
        	}
        }
    	return terms;
    }
    
    public HashMap<String,Float> getSynonymes(String word) { // same as previous but with labels linked to the class
    	HashMap<String,Float> synonymes = new HashMap<String,Float>();
        String query = "PREFIX : <http://ontologies.alwaysdata.net/space#>\n"+
        		"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"+
        		"SELECT ?synonyme WHERE {\n"+
        		  "?subject rdfs:label \""+word+"\"@fr.\n"+
        		  "?subject rdfs:label ?synonyme.\n"+
        		  "FILTER(?synonyme != \""+word+"\"@fr).\n"+
        		"}\n";
            Iterable<Map<String, String>> results = this.sparqlClient.select(query);
            int nbResult = 0;
            for (Map<String, String> result : results) {
                nbResult++;
            }
            
            
            for (Map<String, String> result : results) {
            	ArrayList<String> arr = tokenizeResult(result.get("synonyme"));
            	for (String s : arr){
            		synonymes.put(xml.WordLemmatiser.lemmatize(s),1f);//we had a weight of 1
            	}
            }
            synonymes.put(xml.WordLemmatiser.lemmatize(word), 2f);// for the original word, we give a weight of 2
        return synonymes;
    }
    
    
    public HashMap<String, Float> getWords(String word){ // Fill the HashMap with methods results
    	HashMap<String, Float> words = new HashMap<String, Float>();
    	words.putAll(this.getInstance(word));
    	words.putAll(this.getRelatedTerms(word));
    	words.putAll(this.getSynonymes(word));
    	return words;
    }
    
    public ArrayList<String> tokenizeResult (String s){ // Separate a String with spaces and capital letters
    	ArrayList<String> list = new ArrayList<String>();
    	if(s!=null){
    		StringTokenizer st = new StringTokenizer(s," ,_'-");
    		while (st.hasMoreTokens()) {
    			String str = st.nextToken();
    			ArrayList<String> decompList = decomposeComplexWord(str);
    			for (String e : decompList) {
    				list.add(e);    			
    			}
    			list.add(str);
    		}
    	}
    	return list;
    }
    
    public ArrayList<String> decomposeComplexWord (String s) {// Separate a String with capital letters
    	ArrayList<String> list = new ArrayList<String>();
    	int prevInd = 0;
    	for (int i = 1; i < s.length(); i++){
    		Character c = s.charAt(i);
    		if (Character.isUpperCase(c)) {
    			list.add(s.substring(prevInd, i-1));
    			prevInd = i;
    		}
    	}
    	list.add(s.substring(prevInd));
    	return list;
    }
    
    public static void main(String[] argv){
    	SparqlManager manager = new SparqlManager();
    	HashMap<String, Float> words = manager.getWords("balade");
    	for(Entry<String, Float> entry: words.entrySet()){
    		System.out.println("---"+entry.getKey()+"-----"+entry.getValue());
    	}
    }

}
